﻿using PlutoStudio.Aop;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PlutoStudio
{
    /// <summary>
    /// 
    /// </summary>
    public class CompositionContainer : System.ComponentModel.Composition.Hosting.CompositionContainer
    {
        #region ctor
        /// <summary>
        /// 
        /// </summary>
        public CompositionContainer()
            : base() { }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="providers"></param>
        public CompositionContainer(params ExportProvider[] providers)
            : base(providers) { }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="catalog"></param>
        /// <param name="providers"></param>
        public CompositionContainer(ComposablePartCatalog catalog, params ExportProvider[] providers)
            : base(catalog, providers) { }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="catalog"></param>
        /// <param name="isThreadSafe"></param>
        /// <param name="providers"></param>
        public CompositionContainer(ComposablePartCatalog catalog, bool isThreadSafe, params ExportProvider[] providers)
            : base(catalog, isThreadSafe, providers) { }

        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="definition"></param>
        /// <param name="atomicComposition"></param>
        /// <returns></returns>
        protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
        {
            var exports = base.GetExportsCore(definition, atomicComposition);
            return exports.Select(GetExportsCore);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="export"></param>
        /// <returns></returns>
        protected virtual Export GetExportsCore(Export export)
        {
            if (!export.Metadata.ContainsKey("HasIntercept"))
            {
                return export;
            }
            var attributes = export.Value.GetType().GetCustomAttributes(typeof(InterceptorAttribute), true);
            if (attributes==null)
            {
                return export;
            }
            if (attributes.Count()==0)
            {
                return export;
            }
            var interceptors = attributes.Cast<Castle.DynamicProxy.IInterceptor>().ToArray();
            var generator = new Castle.DynamicProxy.ProxyGenerator();
            var result= new Export(export.Definition, () => generator.CreateClassProxyWithTarget(export.Value.GetType(),export.Value,interceptors));
            return result;
        }
    }
}
